using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using TagTool.Devices;

namespace TagTool.Devices.Midi
{
    #region Midi message handling

    /// <summary> Delegate for midi callback function </summary>
    /// <param name="midiHandle"> Midi device handle </param>
    /// <param name="message"> Midi message </param>
    /// <param name="instance"> Instance parameter (ignored with callbacks) </param>
    /// <param name="param1"> High data </param>
    /// <param name="param2"> Low data </param>
    /// <returns></returns>
    [UnmanagedFunctionPointer(CallingConvention.Winapi)]
    public delegate MMResult MidiOutProc(IntPtr midiHandle, uint message, uint instance, uint param1, uint param2);

    #endregion

    public class MidiOutputDevice : MidiDevice
    {
		private MidiOutputCaps capabilities;

        private MidiOutProc proc;

        // TODO: Declare midi system message handlers
        // TODO: Find out which on which midi input device to receive channel voice messages

        public MidiOutputDevice(uint deviceId)
        	: base(deviceId)
        {
            type = MidiDeviceType.Output;
            proc = new MidiOutProc(OnMidiOut);
        }

        ~MidiOutputDevice()
        {
        	Disconnect();
        }

        public override void Connect()
        {
        	if(deviceHandle != null)
        	{
        		Disconnect();
        	}
            deviceHandle = new IntPtr();
            if(WinMidi.MidiOutOpen(ref deviceHandle, 0, IntPtr.Zero, 0, 0) == MMResult.NoError)
            {
            	connected = true;
            }
        }

        public override void Disconnect()
        {
            if (deviceHandle != IntPtr.Zero)
            {
                if(WinMidi.MidiOutClose(deviceHandle) == MMResult.NoError)
                {
                	connected = false;
                }
            }
        }

        #region Output

        public override MMResult GetDevCaps()
        {
            capabilities = new MidiOutputCaps();
            uint cbMidiOutCaps = (uint)Marshal.SizeOf(capabilities);
            MMResult result = WinMidi.MidiOutGetDevCaps(0, ref capabilities, cbMidiOutCaps);
            return result;
        }

        #endregion Out

        public MMResult OnMidiOut(IntPtr hMidiIn, uint wMsg, uint dwInstance, uint dwParam1, uint dwParam2)
        {
            return MMResult.NoError;
        }
    }
}
